package com.meshnetics.gb.type.impl.zcl;

import com.meshnetics.gb.type.impl.ByteUtils;

import java.nio.ByteBuffer;

/**
 * WRITE DESCRIPTION HERE
 *
 * @author AKovylin
 */
public class Str extends AbstractDataValue implements ZCLInvalidable {
    private final byte[] value;
    private final int length;

    // no checks or cloning of array performed, length not checked
    protected Str(TypeStr type, int length, byte[] value) {
        super(type);
        this.length = length;
        this.value = value;
    }

    public boolean isInvalid() {
        return length == ((TypeStr) dataType).getInvalidLength();
    }

    public int getLength() {
        return length;
    }

    public int getOctetLength() {
        return value == null ? 0 : value.length;
    }

    public int getDataSize() {
        return ((TypeStr) dataType).getLengthFieldSize() + (isInvalid() ? 0 : length);
    }

    public Object toObject() {
        return length == 0 || isInvalid() ? new byte[0] : value.clone();
    }

    public byte[] bytesValue() {
        byte[] bytes = new byte[((TypeStr) dataType).getLengthFieldSize() + length];
        ByteUtils.fillFromLong(length, bytes, 0, bytes.length - length);
        if (length == 0 || isInvalid()) {
            return bytes;
        }
        System.arraycopy(value, 0, bytes, bytes.length - length, length);
        return bytes;
    }

    public void serialize(ByteBuffer bb) {
        ByteUtils.ensureNotNull(bb);
        ByteUtils.ensureCapacity(bb, ((TypeStr) dataType).getLengthFieldSize() + length);
        byte[] bytes = new byte[((TypeStr) dataType).getLengthFieldSize()];
        ByteUtils.fillFromLong(length, bytes, 0, bytes.length);
        ByteUtils.writeToByteBuffer(bb, bytes);
        if (length == 0 || isInvalid()) {
            return;
        }
        ByteUtils.writeToByteBuffer(bb, value);
    }

    public void serializeWithoutLength(ByteBuffer bb, boolean useBufferOrder) {
        ByteUtils.ensureNotNull(bb);
        ByteUtils.ensureCapacity(bb, length);
        if (length == 0 || isInvalid()) {
            return;
        }

        if (useBufferOrder) {
            ByteUtils.writeToByteBuffer(bb, value);
        } else {
            bb.put(value);
        }
    }
}
